/******************************************************************/
/*                                                                */
/*  Winpooch : Windows Watchdog                                   */
/*  Copyright (C) 2004  Benoit Blanchon                           */
/*                                                                */
/*  This program is free software; you can redistribute it        */
/*  and/or modify it under the terms of the GNU General Public    */
/*  License as published by the Free Software Foundation; either  */
/*  version 2 of the License, or (at your option) any later       */
/*  version.                                                      */
/*                                                                */
/*  This program is distributed in the hope that it will be       */
/*  useful, but WITHOUT ANY WARRANTY; without even the implied    */
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       */
/*  PURPOSE.  See the GNU General Public License for more         */
/*  details.                                                      */
/*                                                                */
/*  You should have received a copy of the GNU General Public     */
/*  License along with this program; if not, write to the Free    */
/*  Software Foundation, Inc.,                                    */
/*  675 Mass Ave, Cambridge, MA 02139, USA.                       */
/*                                                                */
/******************************************************************/

// module's interface
#include "MainWindow.h"

// standart headers
#include <tchar.h>

// project's headers
#include "Language.h"
#include "Log.h"
#include "Resources.h"
#include "Version.h"

#define ID_ICON			0
#define ID_ANIM_TIMER		1
#define ID_BALLOON_TIMER	2
#define ANIM_LENGTH		2
#define ANIM_INTERVAL		2000
#define BALLOON_TIMEOUT		10000

#define MAX_ALERT_LEN	256

#define WM_SHELLNOTIFY  WM_USER+1
#define WM_ALERT	WM_USER+2
#define IDM_EXIT	1
#define IDM_DISABLE	2
#define IDM_ENABLE	3
#define IDM_VIEWLOG	4
#define IDM_ABOUT	5

typedef enum {
  STATE_NORMAL,
  STATE_ALERT,
  STATE_DISABLED
} WINPOOCH_STATE ;

// define missings in win32api
#define NIF_INFO 0x00000010
#define NIIF_NONE 0x00000000
#define NIIF_INFO 0x00000001
#define NIIF_WARNING 0x00000002
#define NIIF_ERROR 0x00000003


LRESULT CALLBACK _MainWnd_WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ;


BOOL MainWnd_RegisterClass (HINSTANCE hInstance)
{
  WNDCLASS wc = {
    .lpfnWndProc   = _MainWnd_WindowProc,
    .hInstance     = hInstance,
    .lpszClassName = WC_MAINWINDOW
  } ;
     
  return RegisterClass (&wc) ;
}

HWND MainWnd_CreateWindow (HINSTANCE hInstance)
{
  return CreateWindow (WC_MAINWINDOW, TEXT(""), 0,
		       0, 0, 1, 1, NULL, NULL, hInstance, NULL) ;
}

VOID MainWnd_SendAlert (HWND hwnd, ALERTTYPE iAlertType, LPCTSTR szMessage) 
{
  SendMessage (hwnd, WM_ALERT, iAlertType, (LPARAM)szMessage) ;
}

VOID MainWnd_SendAlertf (HWND hwnd, ALERTTYPE iAlertType, LPCTSTR szFormat, ...)
{
  TCHAR szMessage[MAX_ALERT_LEN] ;
  va_list args ;

  va_start (args, szFormat) ;

  wvsprintf (szMessage, szFormat, args) ;
  
  va_end (args) ;
  
  MainWnd_SendAlert (hwnd, iAlertType, szMessage) ;
}


LRESULT CALLBACK _MainWnd_WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  POINT pt ;
  int i ;

  static NOTIFYICONDATA nid ;
  static HMENU hPopupMenu ;
  static HICON aAnimIcons[ANIM_LENGTH] ;
  static HICON hAlertIcon, hDisabledIcon ;
  static int iAnimPos ;
  static HINSTANCE hInstance ;
  static TCHAR szBalloon[256] ;
  static WINPOOCH_STATE state ;

  switch( message )
    {

    case WM_CREATE:

      // save instance handle
      hInstance = ((CREATESTRUCT*)lParam)->hInstance ;
      
      // initial state : enabled
      state = STATE_NORMAL ;

      // create menu
      hPopupMenu = CreatePopupMenu () ;
      AppendMenu (hPopupMenu, MF_STRING, IDM_ABOUT, STR(_ABOUT)) ;
      AppendMenu (hPopupMenu, MF_SEPARATOR, 0, NULL) ;
      AppendMenu (hPopupMenu, MF_STRING, IDM_DISABLE, STR(_DISABLE)) ;
      AppendMenu (hPopupMenu, MF_STRING, IDM_VIEWLOG, STR(_VIEW_LOG)) ;
      AppendMenu (hPopupMenu, MF_SEPARATOR, 0, NULL) ;
      AppendMenu (hPopupMenu, MF_STRING, IDM_EXIT, STR(_EXIT)) ;
       
      // load icons
      for( i=0 ; i<ANIM_LENGTH ; i++ )
	aAnimIcons[i] = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_TRAY0+i)) ;
      hAlertIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ALERT)) ;
      hDisabledIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_DISABLED)) ;

      // add to tray
      nid.cbSize = sizeof (nid) ;
      nid.hWnd   = hwnd ;
      nid.uID    = ID_ICON ;
      nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP ;
      nid.uCallbackMessage = WM_SHELLNOTIFY ;
      nid.hIcon  = aAnimIcons[0] ;
      lstrcpy (nid.szTip, TEXT(APPLICATION_NAME)) ;
      Shell_NotifyIcon (NIM_ADD, &nid) ;

      // create icon animation timer
      SetTimer (hwnd, ID_ANIM_TIMER, ANIM_INTERVAL, NULL) ;

      return 0 ; // case WM_CREATE:

    case WM_ENDSESSION:
      DestroyWindow (hwnd) ;
      return 0 ; // case WM_ENDSESSION:

    case WM_DESTROY:

      KillTimer (hwnd, ID_ANIM_TIMER) ;
      for( i=0 ; i<ANIM_LENGTH ; i++ )
	CloseHandle (aAnimIcons[i]) ;
      CloseHandle (hAlertIcon) ;
      Shell_NotifyIcon (NIM_DELETE, &nid) ;
      DestroyMenu (hPopupMenu) ;
      PostQuitMessage (0) ;

      return 0 ; // case WM_DESTROY:


    case WM_COMMAND:

      if( lParam==0 )  // menu command
	{
	  switch( LOWORD(wParam) )
	    {
	    case IDM_ABOUT:
	      MessageBox (hwnd, STR(_ABOUT_CONTENT), STR(_ABOUT), 0) ;
	      break ;

	    case IDM_ENABLE:
	      state = STATE_NORMAL ;
	      nid.uFlags = NIF_ICON ;
	      nid.hIcon  = aAnimIcons[0] ;
	      Shell_NotifyIcon (NIM_MODIFY, &nid) ;
	      ModifyMenu (hPopupMenu, IDM_ENABLE, MF_BYCOMMAND,
			  IDM_DISABLE, STR(_DISABLE)) ;
	      break ;
	      
	    case IDM_DISABLE:
	      state = STATE_DISABLED ;
	      nid.uFlags = NIF_ICON ;
	      nid.hIcon  = hDisabledIcon ;
	      Shell_NotifyIcon (NIM_MODIFY, &nid) ;	
	      ModifyMenu (hPopupMenu, IDM_DISABLE, MF_BYCOMMAND,
			  IDM_ENABLE, STR(_ENABLE)) ;	  
	      break ;

	    case IDM_VIEWLOG:
	      ShellExecute (hwnd, NULL, Log_GetPath(), NULL, NULL, SW_SHOW) ;
	      break ;

	    case IDM_EXIT:
	      DestroyWindow (hwnd) ;
	      break ;
	    }
	  return 0 ;
	} // menu command

      break ; // case WM_COMMAND:

    case WM_SHELLNOTIFY:

      if( wParam==ID_ICON )
	{
	  switch( lParam ) 
	    {
	    case WM_RBUTTONDOWN:
	      GetCursorPos (&pt) ;
	      SetForegroundWindow (hwnd) ;
	      TrackPopupMenu (hPopupMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, hwnd, NULL) ;
	      PostMessage (hwnd, WM_NULL, 0, 0) ;
	      break ;	   
	    }
	} 

      return 0 ; // case WM_SHELLNOTIFY:


    case WM_TIMER:

      switch( wParam )
	{
	case ID_ANIM_TIMER:
	  if( state==STATE_NORMAL )
	    {
	      iAnimPos++ ;
	      iAnimPos %= ANIM_LENGTH ;
	      nid.uFlags = NIF_ICON ;
	      nid.hIcon  = aAnimIcons[iAnimPos] ;
	      Shell_NotifyIcon (NIM_MODIFY, &nid) ;
	    }
	  break ;

	case ID_BALLOON_TIMER:
	  if( state==STATE_ALERT )
	    {
	      state = STATE_NORMAL ;
	      KillTimer (hwnd, ID_BALLOON_TIMER) ;
	      SetTimer (hwnd, ID_ANIM_TIMER, ANIM_INTERVAL, NULL) ;
	    }
	  break ;	  
	}

      return 0 ; // case WM_TIMER:

    case WM_ALERT:

      // no alert when disabled
      if( state==STATE_DISABLED && wParam==ALERT_DETECTION )
	return 0 ;

      if( state==STATE_ALERT )
	KillTimer (hwnd, ID_BALLOON_TIMER) ;      

      // play sound
      if( wParam==ALERT_DETECTION && state!=STATE_ALERT)
	PlaySound (MAKEINTRESOURCE(IDW_POOCH), hInstance, SND_ASYNC|SND_RESOURCE) ;
      
      if( state==STATE_ALERT && _tcslen(szBalloon)+_tcslen((LPCTSTR)lParam)+2<255 ) 
	{
	  _tcscat (szBalloon, TEXT("\r\n")) ;
	  _tcscat (szBalloon, (LPCTSTR)lParam) ;
	}
      else _tcsncpy (szBalloon, (LPCTSTR)lParam, 255) ;

      state = STATE_ALERT ;
      
      _tcsncpy (nid.szInfo, szBalloon, 255) ;
      _tcsncpy (nid.szInfoTitle, TEXT(APPLICATION_NAME), 64) ;      
      nid.uFlags = NIF_INFO | NIF_ICON ;
      nid.dwInfoFlags = NIIF_WARNING ;
      nid.uTimeout = BALLOON_TIMEOUT ;
      nid.hIcon  = hAlertIcon ;
      Shell_NotifyIcon (NIM_MODIFY, &nid) ;

      SetTimer (hwnd, ID_BALLOON_TIMER, BALLOON_TIMEOUT, NULL) ;

      return 0 ;
      
    } // switch( message )

  return DefWindowProc (hwnd, message, wParam, lParam) ;
}
